home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
090
/
byteibm.arc
/
PERPROPC.C
< prev
next >
Wrap
C/C++ Source or Header
|
1985-07-12
|
20KB
|
594 lines
/*
LISTING 1 - AN EXAMPLE FEATURES TABLE
*/
/*
This code contains a C language Features Table which contains the location
and copyright string that uniquely identify a machine. In addition to the
copyrights, the bit fields for the FEATURES and VIDEO_FEATURES variables
are defined. Note that this code is compiled with the Lattice C Compiler
version 2.15, using -md -n options. Copyright (c) 1986 Dan Jacobs and
Joel Rosenblum for public, unrestricted use.
*/
/* bit flags for FEATURES */
#define IBMPC 0x0100 /* IBM PC, XT, Portable, */
#define IBMPCAT 0x0200 /* IBM AT */
#define IBMCOMPAT 0x0400 /* IBM PC BIOS Compatible */
#define IBM_CONVERT 0x0800 /* IBM Convertible */
#define GENERIC 0x1000 /* Assumed Generic PC */
#define NO_DMA 0x2000 /* Machine has no DMA */
#define WANG 0x4000 /* Wang PC Special Case*/
#define TIPROF 0x8000 /* TI Professional PC Special Case */
#define CPU_88 0x0001 /* 8088, 8086 Processor */
#define CPU_186 0x0002 /* 80188, 80186 Processor */
#define CPU_286 0x0004 /* 80286 Processor */
#define CPU_V20 0x0008 /* V20, V30 Processor */
#define NDP 0x0010 /* 8087, 80287 Math Co-processor */
/* bit flags for VIDEO_FEATURES */
#define CGA 0x0001 /* IBM Color Graphics Adapter */
#define MONO 0x0002 /* IBM Monochrome Adapter */
#define HERCULES 0x0004 /* Hercules Monochrome Adapter Card */
#define PGA 0x0008 /* IBM Professional Graphics Adapter */
#define EGA_MONO 0x0010 /* w/Monochrome Monitor */
#define EGA_COLOR 0x0020 /* w/Color Monitor */
#define EGA_HIGH 0x0040 /* w/High Resolution Color Monitor */
#define UNKNOWN 0x0080 /* Unknown Graphics Type */
#define ANSI 0x0100 /* ANSI.SYS installed */
/* Additional bit fields may also be defined, please see TABLE 1 for suggestions */
struct machine_info {
char *logo; /* Unique copyright string */
long addr; /* String memory location */
/* Note: actually (char *) must be (long) to pass lattice C */
int type; /* Machine attributes */
} feature_table[] = {
/* copyright notice, physical address, pctype */
{ "IBM", 0xFE00EL, IBMPC|IBMCOMPAT}, /* All IBMs */
{ "COMPAQ", 0xFFFEAL, IBMCOMPAT}, /* All COMPAQs */
{ "Corona", 0xFE00F, IBMCOMPAT}, /* Old Version Corona */
{ "Corona", 0xFE01A, IBMCOMPAT}, /* Version 3.10 ROM Corona (also Phillips) */
{ "M.P.C.", 0xFDB2D, IBMCOMPAT}, /* New Columbia */
{ "Columbia", 0xFF768, IBMCOMPAT}, /* Old Columbia */
{ "Eagle PC", 0xFFFAA, IBMCOMPAT}, /* Eagle PC */
{ "Eagle PC", 0xFF810, IBMCOMPAT}, /* Eagle PC Plus */
{ "Zenith", 0xFB000, IBMCOMPAT}, /* Zenith Data Systems */
{ "Zenith", 0xFC2FF, GENERIC}, /* Zenith 100 */
{ "MITSUBISHI", 0xFC02A, IBMCOMPAT}, /* Sperry PC and Leading Edge */
{ "TVS", 0xFE003, IBMCOMPAT}, /* Televideo */
{ "OSM", 0xFFFF5, IBMCOMPAT}, /* OSM Rom Version 3.6 or later */
{ "OLIVETTI", 0xFC050, IBMCOMPAT}, /* AT&T-IS PC6300 and Xerox */
/* NOTE: AT&T is not supporting V1.0 ROMs */
{ "WANG", 0xFFFC2, WANG|GENERIC}, /* WANG professional */
{ "ADDS", 0xFC050, IBMCOMPAT}, /* Applied Data Digital Systems Model PC/I */
{ "CROS", 0xFE000, IBMCOMPAT}, /* Seattle Telecom Turbo Boards */
{ "PCPI", 0xFE00F, IBMCOMPAT}, /* Personal Computer Products */
{ "TAVA", 0xFE018, IBMCOMPAT}, /* Tava PC */
{ "Tandy", 0xFC02B, IBMCOMPAT|NO_DMA}, /* Tandy 1000 has no DMA unless memory upgrade board installed */
{ "Tandon", 0xFC013, IBMCOMPAT}, /* Tandy 1200 */
{ "Texas", 0xFE022, TIPROF}, /* TI Professional V1.23 & V2.11 SYSROM */
{ "American", 0xFE004, IBMCOMPAT}, /* American PC lookalike */
{ "STD", 0xFE00EL, IBMCOMPAT}, /* STD Turbo Boards in IBMs */
{ "STD", 0xFFFEAL, IBMCOMPAT}, /* STD Turbo Boards in COMPAQs */
{ "TOMCAT", 0xFE028, IBMCOMPAT}, /* Tomcat AT clone */
{ "WYSE", 0xFC003, IBMCOMPAT}, /* WYSE PC BIOS Version 1.08 */
{ "Hewlett-Packard", 0xF0024, IBMCOMPAT}, /* Hewlett-Packard Vectra AT Compatible */
{ "Morrow", 0xFE073, IBMCOMPAT}, /* Morrow Pivot II & Zenith 171 Desktops */
/* Additional machines are added to the list starting here */
{ NULL, NULL, 0}
};
-------------------------------------------------------------------------------
/*
LISTING 2 - DETERMINING MACHINE COMPATIBILITY
*/
/*
This code shows how the Features Table is used to set up
the bit flags in the FEATURES variable. Once FEATURES
is set for the current machine, your other program
modules can use it to determine what section of code
should be executed to yield the best program performance.
Copyright (c) 1986 Dan Jacobs and Joel Rosenblum
Compiled using Lattice C ver 2.15, using -md -n options
*/
unsigned int video_features; /* global variable which holds video attributes */
unsigned int set_features()
{
char *cp; /* Pointer */
struct machine_info *p; /* Features Table Structure */
unsigned int feature; /* FEATURES bit field variable */
/* Assume the PC is generic to start */
feature = GENERIC; /* default to generic */
/*
A psuedo code example of how to override the automatic set of FEATURES
assuming that either a slash option or an DOS environment variable is
set. Your actual code will depend upon how you do the parsing. See
the section on "using the machine's copyright notice to determine
compatibility" in our text.
begin pseudo code example --
if ((/IBM entered on command line) |
(compatibility = IBM is in the environment)) {
feature = IBMCOMPAT;
goto cpu_test;
}
-- end psudo code example */
for (p = feature_table; p->addr != NULL; p++) /* if next table entry is NULL, then end loop */
if (strncmp((char *) p->addr, p->logo, strlen(p->logo)) == 0) {
feature = p->type;
break;
}
if (feature & IBMPC) { /* IBM Personal Computers */
cp = (char *) 0xFFFFE; /* physical address 0FFFF:E */
switch (*cp) {
case 0xF9: /* IBM Convertible */
feature |= IBM_CONVERT;
break;
case 0xFC: /* IBM AT */
feature |= IBMPCAT | CPU_286;
break;
case 0xFD: /* IBM PC JR */
feature |= NO_DMA;
break;
case 0xFE: /* IBM XT or Portable */
case 0xFF: /* IBM PC */
break;
default:
break; /* unknown IBM type */
}
}
/* add the cpu type to FEATURES -- see listing 3 */
feature = cputest(feature);
/* check for numeric data processor -- see listing 4 */
feature = test_ndp(feature);
/* add the video display type to VIDEO_FEATURES -- see listing 6 */
video_features = video_test(feature);
/* check if ANSI.SYS is present -- see listing 7 */
if (check_ansi()) {
video_features |= ANSI;
} else {
putch(0x0D); /* this cleans up any garbage left on the screen */
putch(' '); /* by the ansi check if ANSI.SYS is not present */
putch(' ');
putch(' ');
putch(' ');
putch(0x0A);
putch(0x0D);
}
return (feature);
}
_______________________________________________________________________________
/*
LISTING 5B - ILLUSTRATION OF TIMING DELAYS, C CALLING ROUTINE
*/
/*
This driver provides an example of how to use cal.asm for
delay calibrate routines. The routine will print the delay
according to the speed of the processor. The closer you
make the loops to your actual code, the more accurate the
calculation will be. You should then adjust your actual
program delay proportional to the results of this test.
*/
#include <stdio.h>
static char id[] = "#PROGRAM: calibrate driver (hzm)";
/*
* Global variables:
*/
int us500;
int ms2;
/*
* init -- calibrate the delay counters
*/
static
init()
{
us500 = delaycal(500);
ms2 = delaycal(2000);
printf("%d loops equals 500 microseconds.\n", us500);
printf("%d loops equals 2 milliseconds.\n", ms2);
}
/*
* delay1 -- delay for .5 sec (= 1000 * 500 usec)
*/
static
delay1()
{
char before[4];
char after[4];
int i;
printf("\nNow, delay 1000 * 500 usec...\n");
dostime(&before);
for (i = 0; i < 1000; i++) del500u();
dostime(&after);
printf(" Start: %02d:%02d:%02d.%02d\n",
before[1], before[0], before[3], before[2]);
printf(" End: %02d:%02d:%02d.%02d\n",
after[1], after[0], after[3], after[2]);
}
/*
* delay2 -- delay for 4.0 sec (= 2000 * 2000 usec)
*/
static
delay2()
{
char before[4];
char after[4];
int i;
printf("\nNow, delay 2000 * 2000 usec...\n");
dostime(&before);
for (i = 0; i < 2000; i++) del2m();
dostime(&after);
printf(" Start: %02d:%02d:%02d.%02d\n",
before[1], before[0], before[3], before[2]);
printf(" End: %02d:%02d:%02d.%02d\n",
after[1], after[0], after[3], after[2]);
}
/*
* driver main program:
*/
main(argc, argv)
int argc; char *argv[];
{
init();
delay1();
delay2();
exit(0);
}
-------------------------------------------------------------------------------
/*
LISTING 7 - TEST FOR PRESENCE OF ANSI.SYS
*/
/*
This code contains the check for the presence of ANSI.SYS. If
found, the appropriate bit in VIDEO_FEATURES is set. This code
is called from listing 2 and is compatible with the Lattice C
Compiler.
Copyright (c) 1986 Dan Jacobs and Joel Rosenblum
Compiled using Lattice C ver 2.15, using -md -n options
*/
#include "dos.h"
#define FAIL 1
#define OK 0
#define ANSI 1
#define NOT_ANSI 0
int line, line2, column, column2;
union REGS in, out; /* defined in dos.h file of Lattice C Compiler */
/****************************************************************************
NAME
check_ansi
SYNOPSIS
Checks to see if ANSI.SYS is installed on your machine
by doing an ansi "report cursor position" call twice
in a row to make sure each call returns a value, and
that the values match for two successive calls. For
further information on ANSI.SYS, see the IBM DOS
technical reference.
RETURN VALUE
1 if ansi.sys is installed
0 otherwise
*****************************************************************************/
check_ansi()
{
dump_key_buffer();
cputs("\x1B[6n"); /* report cursor position command */
if (get_line_column()) {
dump_key_buffer();
return NOT_ANSI; /* no cursor position came in */
}
line2 = line; /* save the reported values */
column2 = column;
dump_key_buffer();
cputs("\x1B[6n"); /* try it one more time */
if (get_line_column()) {
dump_key_buffer();
return NOT_ANSI;
}
dump_key_buffer();
if (line2 != line || column2 != column) return NOT_ANSI;
return ANSI;
}
/***************************************************************************
NAME
get_line_column
SYNOPSIS
checks to see if there are two keystokes
the keyboard buffer (K.B.) and if so,
them in the global variables line
column.
****************************************************************************/
get_line_column()
{
if (!(line = check_key())) return FAIL;
if (!(column = check_key())) return FAIL;
return OK;
}
/***************************************************************************
NAME
check_key
SYNOPSIS
returns keystroke left in K.B. if a keystroke exists there
****************************************************************************/
check_key()
{
int c;
for (c = 0; c < 100; c++)
; /* do nothing but wait */
in.h.dl = 0xFF;
in.h.ah = 0x6;
c = intdos(&in, &out);
if (c & 0x40) return 0;
return (int)out.h.al;
}
/***************************************************************************
NAME
dump_key_buffer
SYNOPSIS
clears K.B.
****************************************************************************/
dump_key_buffer()
{
in.h.dl = 0xFF;
in.h.al = 0x06;
in.h.ah = 0x0C;
intdos(&in, &out);
}
-------------------------------------------------------------------------------
/*
LISTING 8 - EXAMPLE VIDEO CHARACTER OUTPUT ROUTINE
*/
/*
This code contains a C language example that uses the bit
fields contained within the FEATURES variable to determine
if it is possible to display the IBM extended character
set on the machine. We assume these characters may be
displayed if the machine is IBMCOMPAT. Note that this
may be called from other modules in your program without
regard to hardware considerations.
Copyright (c) 1986 Dan Jacobs and Joel Rosenblum
Compiled using Lattice C ver 2.15, using -md -n options
*/
extern unsigned int features; /* see definition */
/* position of characters in box_char */
#define TOP_LEFT 0
#define TOP_SIDE 1
#define TOP_RIGHT 2
#define SIDES 3
#define BOTTOM_LEFT 4
#define BOTTOM_SIDE 5
#define BOTTOM_RIGHT 6
char box_char[2][7] = {
{0xDA, 0xC4, 0xBF, 0xB3, 0xC0, 0xC4, 0xD9}, /* expanded char codes */
{0x2B, 0x2D, 0x2B, 0x7C, 0x2B, 0x2D, 0x2D} /* replacement char codes
to use when no extended
codes can be used */
};
/*****************************************************************************
NAME
draw_box
SYNOPSIS
Draws a box of size, length, and width at the row
and column specified. Notice how the characters
used for the box are changed based on the
availability of the extended set. (Those
characters only exist on IBM compatibles).
*****************************************************************************/
draw_box(row, column, length, depth)
int row, column, length, depth;
{
int i;
int char_set; /* tells which row of box_char to use based
on the the IBMCOMPAT bit in features, use row
0, which contains extended chars, if IBMCOMPAT
otherwise, use row 1 which contains standard
ASCII replacements for the extended set */
char_set = features & IBMCOMPAT ? 0 : 1;
move_cursor(row, column); /* First, draw left corner */
/* Move_curser is in listing 9. It moves the cursor to row, column
by determining the machine's video features contained in the bit
flags in FEATURES. You notice that your program does not need
to worry about the details of how to move the cursor depending
upon which machine is used. That leaves you free to solve more
important problems */
putchars(box_char[char_set][TOP_LEFT], 1);
/* Putchars is a routine which puts the char passed in the first arg
out to the screen the number of times specified by the second arg.
Putchar also decides which method it will use to output that char
based on the type of equiptment installed on your machine. See
listing 9 for move_cursor detail */
move_cursor(row, column+1); /* now the top side */
putchars(box_char[char_set][TOP_SIDE], length-2);
move_cursor(row, column+length-1); /* next top right corner */
putchars(box_char[char_set][TOP_RIGHT], 1);
for(i = 1; i < length-1; i++) { /* Vertical sides */
move_cursor(row+i, column);
putchars(box_char[char_set][SIDES], 1);
move_cursor(row+i, column+length-1);
putchars(box_char[char_set][SIDES], 1);
}
move_cursor(row+length-1, column); /* bottom left corner */
putchars(box_char[char_set][BOTTOM_LEFT], 1);
move_cursor(row+length-1, column+1 ); /* bottom side */
putchars(box_char[char_set][BOTTOM_SIDE], length-2);
move_cursor(row+length-1, column+length-1); /* bottom right corner */
putchars(box_char[char_set][BOTTOM_RIGHT], 1);
}
-------------------------------------------------------------------------------
/*
LISTING 9 - EXAMPLE VIDEO CURSOR POSITIONING ROUTINE
*/
/*
This routine handles the details of cursor positioning based on
the bits set in the variables FEATURES and VIDEO_FEATURES. It
is called from the draw_box routine in listing 8, and illustrates
how common machine dependent routines should be written. Note
a similar type of routine should exist in your program to handle
bit-mapped graphics-related calls.
Compiled using Lattice C ver 2.15, using -md -n options
*/
extern unsigned int features; /* global variable which holds machine features */
extern unsigned int video_features; /* global variable which holds video-related features */
char *screen_buff; /* pointer to buffer of 2000 (80*25) chars which is big
enough to hold the ASCII charactures for a complete
video page */
char *screen_pos; /* pointer into screen_buff at current cursor position */
char page_no; /* previously set video page number */
char string[80]; /* string to use for ASCII calls */
/****************************************************************************
NAME
move_cursor
SYNOPSIS
moves the cursor to row, column on the video display
note that the routine decides which method to use
based on bits set in both FEATURES and VIDEO_FEATURES
*****************************************************************************/
move_cursor(row, column)
int row, column;
{
union REGS inregs, outregs; /* defined in dos.h */
if (features & IBMCOMPAT) { /* use int 10 video bios */
inregs.h.ah = 2; /* set cursor position */
inregs.h.dl = column;
inregs.h.dh = row;
inregs.h.bh = page_no; /* page number */
int86(0x10, &inregs, &outregs); /* do bios int 10 */
} else if (video_features & ANSI) { /* need to do ansi calls */
sprintf(string, "\x1B[%d;%df$", ++row, ++column);
dos_puts(string); /* dos_puts is a routine that calls dos and
prints string using function 9, print string */
} else { /* dos generic mode */
screen_pos = screen_buff + row * 80 + column;
}
/* NOTE: In DOS generic mode we keep a buffer (screen_buff)
big enough to hold one video page of ASCII text. In all
of the calls that write to video, we move the chars into
screen_buf at the pheudo cursor position, screen_pos.
When we have completed updating the memory-based page,
we write the ASCII chars from the memory buffer to the
actual screen using standard dos calls */
}